package com.youlu.campus.service.order.impl;

import com.alibaba.fastjson.JSON;
import com.kuaidi100.sdk.response.SubscribePushData;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.CaInfo;
import com.youlu.campus.entity.OOrderInfo;
import com.youlu.campus.entity.OrderInfo;
import com.youlu.campus.entity.PlatformConfig;
import com.youlu.campus.entity.SubOrderInfo;
import com.youlu.campus.entity.VO.req.LogisticsOrderQueryVO;
import com.youlu.campus.entity.card.entity.VipGoods;
import com.youlu.campus.entity.order.LogisticsOrder;
import com.youlu.campus.entity.order.dto.LogisticsOrderDto;
import com.youlu.campus.entity.order.dto.LogisticsOrderQueryDto;
import com.youlu.campus.entity.order.dto.LogisticsSubOrderQueryDto;
import com.youlu.campus.service.ca.CaInfoService;
import com.youlu.campus.service.notify.KuaiDi100Service;
import com.youlu.campus.service.order.LogisticsOrderService;
import com.youlu.campus.service.order.OrderService;
import com.youlu.campus.service.platform.PlatformConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class LogisticsOrderServiceImpl implements LogisticsOrderService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Lazy
    @Autowired
    private CaInfoService caInfoService;
    @Lazy
    @Autowired
    private OrderService orderService;
    @Lazy
    @Autowired
    private KuaiDi100Service kuaiDi100Service;
    @Lazy
    @Autowired
    private PlatformConfigService platformConfigService;
    /**
     * 有物流信息
     */
    private String HAS_LOGISTICS = "hasLogistics";
    /**
     * 无物流信息
     */
    private String NO_LOGISTICS = "noLogistics";

    @Override
    public boolean create(LogisticsOrder req) {
        req.setId(null);
        req.setCreatedTime(new Date());
        req = mongoTemplate.insert(req);
        if (StringUtils.isNotBlank(req.getId())) {
            return true;
        }
        return false;
    }

    @Override
    public boolean update(LogisticsOrder req) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(req.getId()));
        Update update = new Update();
        boolean updated = false;
        if (StringUtils.isNotBlank(req.getLogisticsNo())) {
            update.set("logisticsNo", req.getLogisticsNo());
            updated = true;
        }
        if (StringUtils.isNotBlank(req.getLogisticsCompany())) {
            update.set("logisticsCompany", req.getLogisticsCompany());
            updated = true;
        }
        if (StringUtils.isNotBlank(req.getLogisticsTips())) {
            update.set("logisticsTips", req.getLogisticsTips());
            updated = true;
        }
        if (StringUtils.isNotBlank(req.getImageUrl())) {
            update.set("imageUrl", req.getImageUrl());
            updated = true;
        }
        if (StringUtils.isNotBlank(req.getItemInfoId())) {
            update.set("itemInfoId", req.getItemInfoId());
            updated = true;
        }
        if (StringUtils.isNotBlank(req.getItemName())) {
            update.set("itemName", req.getItemName());
            updated = true;
        }
        if (StringUtils.isNotBlank(req.getStatus())) {
            update.set("status", req.getStatus());
            updated = true;
        }
        if (StringUtils.isNotBlank(req.getSubOrderItemInfoId())) {
            update.set("subOrderItemInfoId", req.getSubOrderItemInfoId());
            updated = true;
        }
        if (StringUtils.isNotBlank(req.getType())) {
            update.set("type", req.getType());
            updated = true;
        }
        if (Objects.nonNull(req.getNum())) {
            update.set("num", req.getNum());
            updated = true;
        }
        if (Objects.nonNull(req.getTotalFee())) {
            update.set("totalFee", req.getTotalFee());
            updated = true;
        }
        if (Objects.nonNull(req.getShippingTime())) {
            update.set("shippingTime", req.getShippingTime());
            updated = true;
        }
        if (Objects.nonNull(req.getPostageFee())) {
            update.set("postageFee", req.getPostageFee());
            updated = true;
        }
        if (updated) {
            update.set("updatedTime", new Date());
            UpdateResult updateResult = mongoTemplate.updateFirst(query, update, LogisticsOrder.class);
            return updateResult.getModifiedCount() > 0 ? true : false;
        }
        return true;
    }

    @Override
    public LogisticsOrder findOne(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        return mongoTemplate.findOne(query, LogisticsOrder.class);
    }

    @Override
    public boolean delete(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        DeleteResult deleteResult = mongoTemplate.remove(query, LogisticsOrder.class);
        return deleteResult.getDeletedCount() > 0 ? true : false;
    }

    @Override
    public Page<LogisticsOrder> list(LogisticsOrderQueryVO req) {
        log.info(":>>> 开始获取物流订单列表:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || Objects.isNull(req.getPage()) || Objects.isNull(req.getPageSize())) {
            log.error(":>>> 参数错误:分页、页码为空");
            throw new BusinessException("参数错误:分页、页码为空");
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").ne(true));
        long count = mongoTemplate.count(query, LogisticsOrder.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<LogisticsOrder> infos = mongoTemplate.find(query.with(pageRequest), LogisticsOrder.class);
        return PageableExecutionUtils.getPage(infos, pageRequest, () -> count);
    }

    @Override
    public boolean handle(LogisticsOrderDto req, String mode) {
        log.info(":>>>  开始处理物流信息:{}", JSON.toJSON(req));
        final String itemInfoId = req.getItemInfoId();
        CaInfo caInfo = caInfoService.findOne(itemInfoId);
        if (Objects.isNull(caInfo)) {
            log.error(":>>> 商品不存在,id=:{}", itemInfoId);
            return false;
        }
        Date date = new Date();
        if (Boolean.TRUE.equals(caInfo.getCombinedCommodity())) {
            log.info(":>>>  商品是组合装:{}", req.getItemInfoId());
            if (Objects.isNull(req.getChildItemIds()) || CollectionUtils.isEmpty(req.getChildItemIds())) {
                log.error(":>>> 组合装商品发货子商品不能为空,orderNo:{},subOrderNo:{},itemId:{}", req.getOrderNo(),
                        req.getSubOrderNo(), req.getItemInfoId());
                return false;
            }
            for (String childItemId : req.getChildItemIds()) {
                boolean exist = existWith(req.getOrderNo(), req.getSubOrderNo(), req.getLogisticsNo(), childItemId);
                if (exist) {
                    continue;
                }
                boolean existItem = existWithItemInfoId(req.getOrderNo(), req.getSubOrderNo(), childItemId);
                LogisticsOrder insert = new LogisticsOrder();
                insert.setId(null);
                insert.setActivityId(req.getActivityId());
                insert.setCreatedTime(date);
                insert.setLogisticsNo(req.getLogisticsNo());
                insert.setLogisticsCompany(req.getLogisticsCompany());
                insert.setOrderNo(req.getOrderNo());
                insert.setONo(req.getSubOrderNo());
                insert.setItemInfoId(childItemId);
                insert.setShippingTime(req.getShippingTime());
                insert.setImageUrl(caInfo.getMainImageUrl());
                insert.setItemName(caInfo.getName());
                insert.setActivityId(req.getActivityId());
                insert.setType(req.getType());
                insert.setPrice(caInfo.getPrice());
                insert.setSubOrderItemInfoId(itemInfoId);
                // 待收货
                insert.setStatus("4");
                if (existItem) {
                    insert.setReissue(true);
                }
                this.create(insert);
            }
        } else {
            boolean exist = existWith(req.getOrderNo(), req.getSubOrderNo(), req.getLogisticsNo(), itemInfoId);
            if (exist) {
                return true;
            }
            boolean existItem = existWithItemInfoId(req.getOrderNo(), req.getSubOrderNo(), itemInfoId);
            LogisticsOrder insert = new LogisticsOrder();
            insert.setActivityId(req.getActivityId());
            insert.setId(null);
            insert.setCreatedTime(date);
            insert.setLogisticsNo(req.getLogisticsNo());
            insert.setLogisticsCompany(req.getLogisticsCompany());
            insert.setOrderNo(req.getOrderNo());
            insert.setONo(req.getSubOrderNo());
            // 非组合装，子订单的商品和物流单商品一样
            insert.setItemInfoId(itemInfoId);
            insert.setSubOrderItemInfoId(itemInfoId);
            insert.setShippingTime(req.getShippingTime());
            insert.setImageUrl(caInfo.getMainImageUrl());
            insert.setItemName(caInfo.getName());
            insert.setActivityId(req.getActivityId());
            insert.setType(req.getType());
            insert.setPrice(caInfo.getPrice());
            // 待收货
            insert.setStatus("4");
            if (existItem) {
                insert.setReissue(true);
            }
            this.create(insert);
            log.info(":>>>  商品不是组合装:{}", req.getItemInfoId());
            return true;
        }
        return false;
    }

    @Override
    public LogisticsOrderQueryDto getLogisticsOrderDetail(String orderId) {
        log.info("getLogisticsOrderDetail 开始获取物流订单详情:{}", orderId);
        OrderInfo orderInfo = orderService.findOne(orderId);
        if (Objects.isNull(orderInfo)) {
            throw new BusinessException("订单不存在");
        }
        final String orderNo = orderInfo.getOrderNo();
        List<OOrderInfo> subOrderInfos = orderInfo.getOOrderInfos();
        if (CollectionUtils.isEmpty(subOrderInfos)) {
            throw new BusinessException("子订单不存在");
        }
        LogisticsOrderQueryDto res = new LogisticsOrderQueryDto();
        BeanUtils.copyProperties(orderInfo, res);
        res.setItemImageUrl(orderInfo.getImageUrl());
        res.setCategory(orderInfo.getCategory());
        res.setCaPrintName(orderInfo.getCaPrintName());
        res.setExpressFeeTips(orderInfo.getExpressFeeTips());
        res.setExpressFee(orderInfo.getExpressFee());
        res.setUniversityName(orderInfo.getUniversityName());
        res.setCanRefund(orderInfo.getCanRefund());
        res.setCanModifyAddress(orderInfo.getCanModifyAddress());
        res.setCustomerService(orderInfo.getCustomerService());
        res.setPayTime(orderInfo.getPayTime());
        res.setExpressDesc(orderInfo.getExpressDesc());
        res.setDiscountFee(orderInfo.getDiscountFee());
        res.setCouponDiscountFee(orderInfo.getCouponDiscountFee());
        res.setCouponNum(orderInfo.getCouponNum());
        res.setSubsidyOfDoubleCa(orderInfo.getSubsidyOfDoubleCa());
        res.setOriginalTotalFee(orderInfo.getOriginalTotalFee());
        res.setCaPrintName(orderInfo.getCaPrintName());
        res.setExtraExpressFee(orderInfo.getExtraExpressFee());
        //获取是否支持合单功能
        PlatformConfig platformConfig = platformConfigService.find();
        // 合单功能上线时间
        Date thiahTuannTime = new Date(platformConfig.getThiahTuannTime());
        // true:没有升级之前
        boolean old = new Date().before(thiahTuannTime);
        log.info("getLogisticsOrderDetail 订单:{},合单功能上线时间:{},当前时间:{},是否在升级之前:{}", orderId, thiahTuannTime, new Date(), old);
        // 开始扫描子订单
        for (OOrderInfo sub : subOrderInfos) {
            if (StringUtils.isNotBlank(orderInfo.getReDoBatchId()) && Boolean.FALSE.equals(sub.getRealed())) {
                log.error("getLogisticsOrderDetail 非真实订单 订单:{},子订单:{}", orderInfo.getOrderNo(), sub.getOOrderNo());
                continue;
            }
            if(Boolean.FALSE.equals(sub.getShow())){
                log.error("getLogisticsOrderDetail 非显示订单 订单:{},子订单:{}", orderInfo.getOrderNo(), sub.getOOrderNo());
                continue;
            }
            CaInfo caInfo = caInfoService.findOne(sub.getItemInfoId());
            // 如果是组合装，需要遍历子商品的发货情况
            // TODO:特殊处理包宇活动
            if (!"65b8ac2e4071b66f31738851".equals(orderInfo.getActivityId()) && Boolean.TRUE.equals(caInfo.getCombinedCommodity())) {
                List<CaInfo> children = caInfoService.findByParentId(sub.getItemInfoId());
                log.info("getLogisticsOrderDetail 组合装订单 子订单:{},商品:{},子商品数量:{}", sub.getOOrderNo(), caInfo.getId(), children == null ? 0 : children.size());
                if (CollectionUtils.isEmpty(children)) {
                    continue;
                }
                for (CaInfo c : children) {
                    List<LogisticsOrder> logistics = this.findONoAndItemInfoId(orderNo, sub.getOOrderNo(), c.getId());
                    if (CollectionUtils.isEmpty(logistics)) {
                        // 订单提示语需要设置,是组合装情况下需要添加逻辑判断,针对订单的物流状态
                        LogisticsSubOrderQueryDto d = buildWithSubOrder(sub,
                                orderInfo.getActivityId(),
                                c.getName(), c.getPrice(), c.getCertificateImage());
                        this.setOtherInfo(d, c, sub);
                        this.setVirtualItem(d, caInfo, sub);
                        // 升级之前
                        if (old) {
                            if (StringUtils.isNotBlank(sub.getLogisticsNo())) {
                                d.setLogisticsCompany(sub.getLogisticsCompany());
                                d.setLogisticsNo(sub.getLogisticsNo());
                                d.setStatus(sub.getStatus());
                            } else {
                                d.setStatus(sub.getStatus());
                            }
                            d.setTips(sub.getTips());
                        }
                        // 升级之后
                        else {
                            // TODO:需要处理
                            /**
                             * 状态,0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:部分已发货
                             */
                            if ("0".equals(sub.getStatus()) || "1".equals(sub.getStatus()) || "2".equals(sub.getStatus()) ||
                                    "3".equals(sub.getStatus()) || "6".equals(sub.getStatus()) || "7".equals(sub.getStatus()) ||
                                    "8".equals(sub.getStatus())) {
                                d.setStatus(sub.getStatus());
                                d.setTips(sub.getTips());
                            } else if ("4".equals(sub.getStatus()) || "5".equals(sub.getStatus()) || "9".equals(sub.getStatus())) {
//                                d.setStatus("2");
//                                d.setTips("您购买的商品正在定制中，请耐心等待！或可联系在线客服！");
//                                d.setLogisticsCompany("");
//                                d.setLogisticsNo("");
//                                d.setShippingTime(null);
                                d.setStatus(sub.getStatus());
                                d.setTips(sub.getTips());
                                d.setLogisticsCompany(sub.getLogisticsCompany());
                                d.setLogisticsNo(sub.getLogisticsNo());
                                d.setShippingTime(sub.getShippingTime());
                            } else {
                                d.setStatus(sub.getStatus());
                                d.setTips(sub.getTips());
                            }
                        }
                        d.setGift(sub.getGift());
                        res.getSubOrders().add(d);
                    } else {
                        for (LogisticsOrder logisticsOrder : logistics) {
                            // 订单提示语需要设置
                            LogisticsSubOrderQueryDto d = buildWithLogisticsOrder(logisticsOrder,
                                    orderInfo.getActivityId(),
                                    c.getName(), c.getPrice(), c.getCertificateImage());
                            this.setOtherInfo(d, c, sub);
                            this.setVirtualItem(d, caInfo, sub);
                            d.setTips(sub.getTips());
                            d.setGift(sub.getGift());
                            res.getSubOrders().add(d);
                        }

                    }
                }

            } else {
                log.info(":>>> 子订单:{},商品:{},不是组合装", sub.getOOrderNo(), caInfo.getId());
                List<LogisticsOrder> logistics = this.findONo(orderNo, sub.getOOrderNo());
                if (Objects.isNull(logistics) || CollectionUtils.isEmpty(logistics)) {
                    LogisticsSubOrderQueryDto d = buildWithSubOrder(sub,
                            orderInfo.getActivityId(),
                            caInfo.getName(), caInfo.getPrice(), caInfo.getCertificateImage());
                    this.setOtherInfo(d, caInfo, sub);
                    this.setVirtualItem(d, caInfo, sub);
                    // 升级之前
                    if (old) {
                        if (StringUtils.isNotBlank(sub.getLogisticsNo())) {
                            d.setLogisticsCompany(sub.getLogisticsCompany());
                            d.setLogisticsNo(sub.getLogisticsNo());
                            d.setStatus(sub.getStatus());
                        } else {
                            d.setStatus(sub.getStatus());
                        }
                        d.setTips(sub.getTips());
                    }
                    // 升级之后
                    else {
                        // TODO:需要处理
                        /**
                         * 状态,0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:部分已发货
                         */
                        if ("0".equals(sub.getStatus()) || "1".equals(sub.getStatus()) || "2".equals(sub.getStatus()) ||
                                "3".equals(sub.getStatus()) || "6".equals(sub.getStatus()) || "7".equals(sub.getStatus()) ||
                                "8".equals(sub.getStatus())) {
                            d.setStatus(sub.getStatus());
                            d.setTips(sub.getTips());
                        } else if ("4".equals(sub.getStatus()) || "5".equals(sub.getStatus()) || "9".equals(sub.getStatus())) {
                            d.setStatus(sub.getStatus());
                            d.setTips(sub.getTips());
                            d.setLogisticsCompany(sub.getLogisticsCompany());
                            d.setLogisticsNo(sub.getLogisticsNo());
                            d.setShippingTime(sub.getShippingTime());
                        } else {
                            d.setStatus(sub.getStatus());
                            d.setTips(sub.getTips());
                        }
                    }
                    d.setGift(sub.getGift());
                    res.getSubOrders().add(d);
                } else {
                    for (LogisticsOrder logisticsOrder : logistics) {
                        LogisticsSubOrderQueryDto d = buildWithLogisticsOrder(logisticsOrder,
                                orderInfo.getActivityId(),
                                caInfo.getName(), caInfo.getPrice(), caInfo.getCertificateImage());
                        this.setOtherInfo(d, caInfo, sub);
                        this.setVirtualItem(d, caInfo, sub);
                        d.setTips(sub.getTips());
                        d.setGift(sub.getGift());
                        res.getSubOrders().add(d);
                    }
                }
            }
        }
        // 按照包裹排序
        this.sortPackage(res);
        log.info(":>>> 订单物流详情为:{},{}", orderId, JSON.toJSONString(res));
        return res;
    }

    @Override
    public HashMap<String, Object> orderQueryMode(String platform) {
        PlatformConfig config = platformConfigService.find();
        HashMap<String, Object> res = new HashMap<>();
        if (config.getOrderQueryMode().containsKey(platform)) {
            res.put(platform, config.getOrderQueryMode().get(platform));
            return res;
        }
        res.put(platform, "2");
        return res;
    }

    /**
     * 设置其他信息
     *
     * @param d
     * @param caInfo
     * @param sub
     */
    private void setOtherInfo(LogisticsSubOrderQueryDto d, CaInfo caInfo, OOrderInfo sub) {
        d.setTips(sub.getTips());
        d.setONo(sub.getOOrderNo());
        d.setNum(sub.getNum());
        d.setGifted(sub.getGifted());
        d.setSalePrice(caInfo.getPrice());
        d.setRefundStatus(sub.getRefundStatus());
        d.setHasVirtualGoods(caInfo.getHasVirtualGoods());
        d.setTips(sub.getTips());
    }

    private void setVirtualItem(LogisticsSubOrderQueryDto d, CaInfo caInfo, OOrderInfo sub) {
        boolean hasVirtualGoods = caInfo.getHasVirtualGoods() == null ? false : caInfo.getHasVirtualGoods();
        d.setHasVirtualGoods(hasVirtualGoods);
        if (hasVirtualGoods) {
            String goodsId = caInfo.getVirtualGoodsList();
            d.setVirtualGoodsId(goodsId);
            VipGoods goods = mongoTemplate.findById(goodsId, VipGoods.class);
            if (goods != null) {
                d.setVirtualGoodsName(goods.getProductName() + "（" + goods.getExpireDay() + "天内有效）");
                d.setVirtualGoodsCode(goods.getProductId());
            }
        }
    }

    /**
     * 数据按照包裹排序
     *
     * @param res
     */
    private void sortPackage(LogisticsOrderQueryDto res) {
        // 物流和商品的映射
        HashMap<String, List<LogisticsSubOrderQueryDto>> logi = new HashMap<>();
        for (LogisticsSubOrderQueryDto ll : res.getSubOrders()) {
            // r代表一个商品
            LogisticsOrderQueryDto.HasLogisticsInfo r = new LogisticsOrderQueryDto.HasLogisticsInfo();
            r.setLogisticsNo(ll.getLogisticsNo());
            r.setLogisticsCompany(ll.getLogisticsCompany());
            r.setStatus(ll.getStatus());
            r.setTips(ll.getTips());
            r.setShippingTime(ll.getShippingTime());
            if (Objects.nonNull(ll) && !StringUtils.isBlank(ll.getLogisticsNo()) && Objects.nonNull(ll.getShippingTime())) {
                SubscribePushData subscribePushData = kuaiDi100Service.lastLogisticsResult(ll.getLogisticsNo(), res.getOrderNo(), ll.getShippingTime());
                if (Objects.nonNull(subscribePushData)) {
                    r.setSubscribePushData(subscribePushData);
                }
            }
            r.getItemInfos().add(ll);
            String logisticsNo = ll.getLogisticsNo();
            if (StringUtils.isBlank(logisticsNo)) {
                if (res.getInfos().containsKey(NO_LOGISTICS)) {
                    r.setNo(res.getInfos().get(NO_LOGISTICS).size() + 1);
                    res.getInfos().get(NO_LOGISTICS).add(r);
                } else {
                    List<LogisticsOrderQueryDto.HasLogisticsInfo> rr = new ArrayList<>();
                    r.setNo(1);
                    rr.add(r);
                    res.getInfos().put(NO_LOGISTICS, rr);
                }
            } else {
                // 有物流信息
                if (res.getInfos().containsKey(HAS_LOGISTICS)) {
                    List<LogisticsOrderQueryDto.HasLogisticsInfo> ss = res.getInfos().get(HAS_LOGISTICS);
                    boolean ha = false;
                    for (LogisticsOrderQueryDto.HasLogisticsInfo hasLogisticsInfo : ss) {
                        if (hasLogisticsInfo.getLogisticsNo().equals(ll.getLogisticsNo())) {
                            ha = true;
                            hasLogisticsInfo.getItemInfos().add(ll);
                            break;
                        }
                    }
                    if (!ha) {
                        r.setNo(res.getInfos().get(HAS_LOGISTICS).size() + 1);
                        res.getInfos().get(HAS_LOGISTICS).add(r);
                    }
                } else {
                    List<LogisticsOrderQueryDto.HasLogisticsInfo> rr = new ArrayList<>();
                    r.setNo(1);
                    rr.add(r);
                    res.getInfos().put(HAS_LOGISTICS, rr);
                }
            }
        }
    }

    private boolean existWith(String orderNo, String oNo, String logisticsNo, String itemInfoId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo).
                and("oNo").is(oNo).
                and("logisticsNo").is(logisticsNo).and("itemInfoId").is(itemInfoId));
        boolean exist = mongoTemplate.exists(query, LogisticsOrder.class);
        log.info(":>>> 物流订单是否存在:{},orderNo:{},oNo:{},logisticsNo:{},itemInfoId:{}",
                exist, orderNo, oNo, logisticsNo, itemInfoId);
        return exist;
    }

    private boolean existWithItemInfoId(String orderNo, String oNo, String itemInfoId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo).
                and("oNo").is(oNo)
                .and("itemInfoId").is(itemInfoId));
        boolean exist = mongoTemplate.exists(query, LogisticsOrder.class);
        log.info(":>>> 物流订单是否存在:{},orderNo:{},oNo:{},itemInfoId:{}",
                exist, orderNo, oNo, itemInfoId);
        return exist;
    }

    private List<LogisticsOrder> find(String orderNo, String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo).
                and("activityId").is(activityId));
        return mongoTemplate.find(query, LogisticsOrder.class);
    }

    private List<SubOrderInfo> getSubOrders(String orderNo) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo));
        return mongoTemplate.find(query, SubOrderInfo.class);
    }

    private List<LogisticsOrder> findONo(String orderNo, String oNo) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo).
                and("oNo").is(oNo));
        return mongoTemplate.find(query, LogisticsOrder.class);
    }

    private List<LogisticsOrder> findONoAndItemInfoId(String orderNo, String oNo,
                                                      String itemInfoId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orderNo").is(orderNo).
                and("oNo").is(oNo).and("itemInfoId").is(itemInfoId));
        return mongoTemplate.find(query, LogisticsOrder.class);
    }

    private LogisticsSubOrderQueryDto buildWithSubOrder(OOrderInfo sub,
                                                        String activityId,
                                                        String itemName,
                                                        Integer itemPrice, String imageUrl) {
        LogisticsSubOrderQueryDto l = new LogisticsSubOrderQueryDto();
        l.setLogisticsNo(sub.getLogisticsNo());
        l.setActivityId(activityId);
        l.setItemImageUrl(imageUrl);
        l.setItemName(itemName);
        l.setLogisticsCompany(sub.getLogisticsCompany());
        l.setPrice(itemPrice);
        l.setStatus(sub.getStatus());
        l.setItemInfoId(sub.getItemInfo().getId());
        l.setONo(sub.getOOrderNo());
        l.setShippingTime(sub.getShippingTime());
        return l;
    }

    private LogisticsSubOrderQueryDto buildWithLogisticsOrder(LogisticsOrder logisticsOrder,
                                                              String activityId,
                                                              String itemName,
                                                              Integer itemPrice, String imageUrl) {
        LogisticsSubOrderQueryDto l = new LogisticsSubOrderQueryDto();
        l.setLogisticsNo(logisticsOrder.getLogisticsNo());
        l.setActivityId(activityId);
        l.setItemImageUrl(imageUrl);
        l.setItemName(itemName);
        l.setLogisticsCompany(logisticsOrder.getLogisticsCompany());
        l.setPrice(itemPrice);
        l.setStatus(logisticsOrder.getStatus());
        l.setItemInfoId(logisticsOrder.getItemInfoId());
        l.setONo(logisticsOrder.getONo());
        l.setShippingTime(logisticsOrder.getShippingTime());
        l.setTips(logisticsOrder.getLogisticsTips());
        l.setId(logisticsOrder.getId());
        return l;
    }
}
